package gates;

import mathtools.Complex;
import mathtools.Matrix;
import register.Register;

/**
 * <p>AllC Not Gate - an efficient generalized Toffoli gate.</p>
 * <p>The Gate flipes the target qubit if all the other qubits are 1 </p>
 * 
 * @author Richard Inskip
 *
 */
public class AllCnotMatrix extends MatrixGate {
	
	/** Store the target qubit the gate acts on*/	
	private int target;

	/**
	 * Protected constructor to create an instance of this object
	 * 
	 * @param target the target qubit to flip
	 */
	protected AllCnotMatrix(int target){
		this.target=target+1;
		
	}
	
	/** The apply method which will allow the Gate to be appied to the Register.
	 * @param r The Quantum Register
	 */
	public void apply(Register r) {
		if (target > r.getNumQbits() || target < 1){
			throw new IllegalArgumentException("Target qubit not in register. Register size (qubits): " + r.getNumQbits() + " Target qubit: " + target);
		}
		int numStates = r.getNumStates();
		int intervalSize = (int)(numStates/Math.pow(2,target));
		Matrix AllCnot = Matrix.IdentityMatrix(numStates);
		AllCnot.setElement(numStates-1, numStates - 1,new Complex(0)); 
		AllCnot.setElement(numStates-1-intervalSize, numStates-1-intervalSize, new Complex(0));
		AllCnot.setElement(numStates-1-intervalSize, numStates - 1, new Complex(1));
		AllCnot.setElement(numStates-1,numStates-1-intervalSize,new Complex(1));
		r.update(AllCnot.multiplyMatrix(r));
	}

	/**
	 *  Return the name of the matrix.
	 */
	public String getName() {
		return "AllCnot";
	}

}
